package com.service.admin.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.service.admin.base.controller.req.WalletReq;
import com.service.admin.member.controller.rep.RWexcelRep;
import com.service.admin.member.controller.req.MemberRWPageReq;
import com.service.admin.member.controller.req.MemberRechargeReq;
import com.service.admin.member.controller.req.WithdrawReq;
import com.service.admin.member.dto.MemberStoreChange;
import com.service.admin.member.service.MemberService;
import com.service.admin.member.service.MemberStoreService;
import com.service.core.exception.CommonException;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.enums.*;
import com.service.dao.model.Member;
import com.service.dao.query.RWRecordParam;
import com.service.dao.po.RWRecordResultPO;
import com.service.dao.mapper.JournalAccountMapper;
import com.service.dao.mapper.MemberStoreMapper;
import com.service.dao.mapper.RwRecordMapper;
import com.service.dao.model.JournalAccount;
import com.service.dao.model.MemberStore;
import com.service.dao.model.RwRecord;
import com.service.admin.member.service.MemberRWService;
import com.service.utility.common.UUIDUtil;
import com.service.utility.modelmapper.ModelMapperUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <dl>
 * <dt>back-end</dt>
 * <dd>Description:</dd>
 * <dd>Copyright: Copyright (C) 2015</dd>
 * <dd>Company: </dd>
 * <dd>CreateDate: 2019年09月25日</dd>
 * </dl>
 *
 * @author
 */
@Slf4j
@Service
public class MemberRWServiceImpl extends ServiceImpl<RwRecordMapper, RwRecord> implements MemberRWService {

    @Autowired
    private MemberService memberService;

    @Autowired
    private RwRecordMapper rwRecordMapper;

    @Autowired
    private MemberStoreMapper storeMapper;

    @Autowired
    private JournalAccountMapper journalAccountMapper;

    @Autowired
    private MemberStoreService storeService;

    @Value("${rechargePrefix}")
    private String rechargePrefix;

    @Override
    public CommonPageRep<RWRecordResultPO> pageMemberRW(MemberRWPageReq pageReq) {
        Page<RWRecordResultPO> page = PageHelper.startPage(pageReq.getPageNo(), pageReq.getPageSize());
        rwRecordMapper.pageRecord4Admin(buildQueryParam4Mapper(pageReq));
        return CommonPageRep.buildResultRep(page);
    }

    private RWRecordParam buildQueryParam4Mapper(MemberRWPageReq pageReq) {
        RWRecordParam.RWRecordParamBuilder rwBuild =  RWRecordParam.builder();
        if(!pageReq.getCoinType().equals(CoinsEnum.ALL)){
            rwBuild.coinType(pageReq.getCoinType().getCode());
        }
        if(!pageReq.getWalletType().equals(WalletEnums.Type.ALL)){
            rwBuild.walletType(pageReq.getWalletType().getCode());
        }
        return rwBuild.address(pageReq.getAddress())
                .userAccount(pageReq.getUserAccount())
                .payStatus(pageReq.getPayStatus().getCode())
                .optType(pageReq.getOptType())
                .funded(pageReq.getFunded())
                .build();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remittance2Member(RwRecord rwRecord, String txId) {
        //1、减去会员余额中冻结的币
        this.updateMemberFrost(rwRecord);
        //2、修改流水类型
        this.updateJournalAccount(rwRecord.getJaId());
        //3、修改rw记录的状态
        rwRecord.setPayStatus(RwRecordEnum.PayStatus.remittance.getCode());
        this.updateById(rwRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rejectWithdraw(RwRecord rwRecord) {

        JournalAccount journalAccount = journalAccountMapper.selectById(rwRecord.getJaId());
        if (ObjectUtils.isEmpty(journalAccount)) {
            throw new CommonException("会员流水缺失");
        }

        MemberStoreChange memberStoreChange = MemberStoreChange.builder()
                .memberId(rwRecord.getMemberId())
                .coinsId(rwRecord.getCoinsId())
                .coinsName(rwRecord.getCoinsName())
                .changeNum(journalAccount.getJaNum())
                .jaType(MemberJAType.FROST_RELEASE_BY_WITHDRAW_REJECT)
                .remark("提现驳回,提现记录id:" + rwRecord.getId())
                .build();

        Integer jaId = storeService.changeMemberStore(memberStoreChange);

        rwRecord.setJaId(jaId);
        rwRecord.setPayStatus(RwRecordEnum.PayStatus.reject.getCode());
        updateById(rwRecord);
    }


    private void updateMemberFrost(RwRecord rwRecord) {
        MemberStore store = storeMapper.selectByMemberIdAndCoinId4Admin(rwRecord.getMemberId(), rwRecord.getCoinsId());
        if (ObjectUtils.isEmpty(store)) {
            throw new CommonException("会员余额有误");
        }
        BigDecimal total = rwRecord.getRwNum().add(rwRecord.getUsdtFee());
        if(store.getFrostNum().compareTo(total) < 0){
            throw new CommonException("会员冻结余额错误！");
        }
        //冻结里面减掉
        BigDecimal frostNum = store.getFrostNum().subtract(total);
        Integer id = store.getId();
        store = new MemberStore();
        store.setFrostNum(frostNum);
        store.setId(id);
        storeMapper.updateById(store);
    }

    private void updateJournalAccount(Integer jaId) {
        JournalAccount journalAccount = journalAccountMapper.selectById(jaId);
        if (ObjectUtils.isEmpty(journalAccount)) {
            throw new CommonException("会员流水缺失");
        }
        journalAccountMapper.updateById(JournalAccount.builder().id(jaId)
                .jaType(MemberJAType.WITHDRAW.getCode()).build());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recharge(MemberRechargeReq rechargeReq, Member member) {

        MemberJAType memberJAType;
        if(rechargeReq.getType().equals(1)){
            memberJAType = MemberJAType.RECHARGE;
        }else if(rechargeReq.getType().equals(2)){
            memberJAType = MemberJAType.ADMIN_CUT;
        }else{
            throw new CommonException("交易类型参数错误");
        }
        MemberStoreChange memberStoreChange = MemberStoreChange.builder()
                .memberId(member.getId())
                .coinsId(rechargeReq.getCoins().getCode())
                .coinsName(rechargeReq.getCoins().getName())
                .changeNum(rechargeReq.getRechargeNum())
                .jaType(memberJAType)
                .remark("管理员操作")
                .build();

        Integer jaId = storeService.changeMemberStore(memberStoreChange);

        if(rechargeReq.getType().equals(1)){
            RwRecord rwRecord = new RwRecord();
            rwRecord.setMemberId(member.getId());
            rwRecord.setCoinsId(rechargeReq.getCoins().getCode());
            rwRecord.setCoinsName(rechargeReq.getCoins().getName());
            rwRecord.setRwNo(chargeOrderNo());
            rwRecord.setAddrType(rechargeReq.getWalletType().getCode());
            rwRecord.setRwNum(rechargeReq.getRechargeNum());
            rwRecord.setPayStatus(RwRecordEnum.PayStatus.dao_zhang.getCode());
            rwRecord.setOptType(RwRecordEnum.OptType.recharge.getCode());
            rwRecord.setJaId(jaId);
            rwRecord.setCreateTime(new Date());
            save(rwRecord);
        }
    }


    /**
     * 归集钱包处理
     * @param walletReq
     */
    @Override
    public Integer funded(WalletReq walletReq){
        if(walletReq.getIfAll() == 1){
            //确认归集该地址所有
            return baseMapper.fundedAllbyAddr(walletReq.getAddress(),walletReq.getCoinType().getCode());
        }else{
            return baseMapper.fundedById(walletReq.getId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<RWexcelRep> queryWalletExcel(CoinsEnum coinType) {
        List<RwRecord> lists = list(new QueryWrapper<RwRecord>().lambda()
                .eq(RwRecord::getOptType, RwRecordEnum.OptType.withdraw.getCode())
                .eq(RwRecord::getCoinsName,coinType.getName())
                .lt(RwRecord::getPayStatus,RwRecordEnum.PayStatus.dao_zhang.getCode()));
        List<RWexcelRep> updateQuery = lists.stream().map(item -> {
            //TODO 对会员的余额加锁
            //1、减去会员余额中冻结的币
            this.updateMemberFrost(item);
            //2、修改流水类型
            this.updateJournalAccount(item.getJaId());
            item.setPayStatus(RwRecordEnum.PayStatus.remittance.getCode());
            baseMapper.updateById(item);
            return ModelMapperUtil.map(item, RWexcelRep.class);
        }).collect(Collectors.toList());
        if(!ObjectUtils.isEmpty(updateQuery) && updateQuery.size() > 0){
            return updateQuery;
        }else{
            throw new CommonException("没有可导出的记录");
        }
    }

    private String chargeOrderNo() {
        String rwNo = rechargePrefix + UUIDUtil.randomUUID10().substring(0, 8);
        if(!ObjectUtils.isEmpty(getOne(new QueryWrapper<RwRecord>().lambda().eq(RwRecord::getRwNo, rwNo)))){
            return this.chargeOrderNo();
        }
        return rwNo;
    }

}
